package com.ruoyi.cs.service.impl;

import java.math.BigDecimal;
import java.rmi.server.ExportException;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.ruoyi.common.core.domain.Response;
import com.ruoyi.common.core.domain.RollValueItem;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.common.utils.pay.HttpsUtils;
import com.ruoyi.common.yyyoupin.RSAUtils;
import com.ruoyi.common.yyyoupin.bean.SaleCommodityResponse;
import com.ruoyi.common.yyyoupin.bean.SaleResponse;
import com.ruoyi.cs.domain.*;
import com.ruoyi.cs.domain.vo.*;
import com.ruoyi.cs.mapper.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.cs.service.CommonService;
import com.ruoyi.cs.service.ITVipUserService;
import com.ruoyi.cs.service.ITWarService;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.ISysDictTypeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import com.ruoyi.cs.service.ITGoodsService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

/**
 * 饰品信息Service业务层处理
 *
 * @author ruoyi
 * @date 2021-03-25
 */
@Service
@SuppressWarnings("all")
public class TGoodsServiceImpl implements ITGoodsService
{
    private static final Logger log = LoggerFactory.getLogger(TGoodsServiceImpl.class);

    @Autowired
    private TGoodsMapper tGoodsMapper;
    @Autowired
    private TBoxMapper tBoxMapper;
    @Autowired
    private TRollMapper tRollMapper;
    @Autowired
    private TUserMapper tUserMapper;
    @Autowired
    private TBackpackMapper tBackpackMapper;
    @Autowired
    private TGoodsUpgrateMapper tGoodsUpgrateMapper;
    @Autowired
    private TGoodsPoolMapper tGoodsPoolMapper;
    @Autowired
    private ISysDictDataService sysDictDataService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private RedisLock redisLock;
    @Autowired
    private CommonService commonService;
    @Autowired
    private TBackpackOperateMapper tBackpackOperateMapper;
    @Autowired
    private TBalanceChangeMapper balanceChangeMapper;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Autowired
    private ISysDictTypeService iSysDictTypeService;
    @Autowired
    private ITWarService tWarService;
    @Autowired
    private TBackpackDeductionMapper tBackpackDeductionMapper;
    @Autowired
    private ITVipUserService tVipUserService;

    /**
     * 查询饰品信息
     *
     * @param goodsId 饰品信息ID
     * @return 饰品信息
     */
    @Override
    public TGoods selectTGoodsById(String goodsId)
    {
        return tGoodsMapper.selectTGoodsById(goodsId);
    }

    /**
     * 查询饰品信息列表
     *
     * @param tGoods 饰品信息
     * @return 饰品信息
     */
    @Override
    public List<TGoods> selectTGoodsList(TGoods tGoods)
    {
        return tGoodsMapper.selectTGoodsList(tGoods);
    }

    /**
     * 新增饰品信息
     *
     * @param tGoods 饰品信息
     * @return 结果
     */
    @Override
    public int insertTGoods(TGoods tGoods)
    {
        tGoods.setGoodsStocknum(1L);
        tGoods.setGoodsPutnum(1L);
        tGoods.setGoodsStockStatus("0");
        tGoods.setCreateTime(DateUtils.getNowDate());
        return tGoodsMapper.insertTGoods(tGoods);
    }

    /**
     * 修改饰品信息
     *
     * @param tGoods 饰品信息
     * @return 结果
     */
    @Override
    public Response updateTGoods(TGoods tGoods)
    {
        TGoods tGoods1 = tGoodsMapper.selectTGoodsById(tGoods.getGoodsId());
        BigDecimal chance = tGoods1.getGoodsChance();
        tGoods.setUpdateTime(DateUtils.getNowDate());
        tGoods.setGoodsExprice(tGoods.getGoodsPrice());
        tGoodsMapper.updateTGoods(tGoods);


        /**更新饰品的roll区间值*/
        if(!Objects.equals(tGoods.getGoodsChance(),chance)){
            if(tGoods1.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE0) || tGoods1.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE1)
                    || tGoods1.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE5)){
                List<TGoods> tGoodsList = tGoodsMapper.boxGoodsList(tGoods1.getGoodsBelongingType(),tGoods1.getGoodsBelongingId());
                this.toList(tGoodsList);
                tGoodsMapper.updateRollValueRangeBatch(tGoodsList);
            }
        }
        return Response.success();
    }

    public void toList(List<TGoods> tGoodsList){
        tGoodsList = tGoodsList.stream()
                .sorted(Comparator.comparing(TGoods::getGoodsPrice,Comparator.reverseOrder()))
                .collect(Collectors.toList());
        Map<String, Double> resultMap = tGoodsList.stream()
                .collect(Collectors.toMap(
                        t -> t.getGoodsId(),
                        t -> t.getGoodsChance().doubleValue(),
                        (oldValue, newValue) -> oldValue,
                        LinkedHashMap::new
                ));
        Map<String, RollValueItem> resultRollItem = RollValueUtil.calculateItemRanges(resultMap);
        tGoodsList.forEach(bean -> {
            bean.setRollValueRange(JSON.toJSONString(resultRollItem.get(bean.getGoodsId())));
        });
    }

    /**
     * 批量删除饰品信息
     *
     * @param goodsIds 需要删除的饰品信息ID
     * @return 结果
     */
    @Override
    public Response deleteTGoodsByIds(String[] goodsIds)
    {
        TGoods tGoods1 = tGoodsMapper.selectTGoodsById(goodsIds[0]);
        if (tGoods1.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE0)) {
            String lockTime = DateUtils.getTimeAfter(DateUtils.getNowDate(),1);
            lockTime = Long.toString(DateUtils.parseDate(lockTime).getTime());
            String lockKey = Constants.OPENKEY+tGoods1.getGoodsBelongingId();
            String boxIdKey = Constants.BOXIDKEY+tGoods1.getGoodsBelongingId();
            try {
                /**获取锁*/
                boolean lockflag = redisLock.lock(lockKey,lockTime);
                if (!lockflag) {
                    Thread.currentThread().sleep(1000);
                    lockflag = redisLock.lock(lockKey,lockTime);
                }
                if (!lockflag) {
                    log.error("获取批量删除锁失败");
                    return Response.fail(Constants.FAILCODE,"获取批量删除锁失败");

                }else {
                    redisCache.deleteObject(boxIdKey);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                log.error("获取批量删除锁失败,异常：{}",e.getMessage());
                return Response.fail(Constants.FAILCODE,"获取批量删除锁异常");
            }finally {
                redisLock.release(lockKey,lockTime);
            }
        }
        tGoodsMapper.updateDelFlagTGoodsByIds(Constants.DELETE,goodsIds);


        /**更新饰品roll值区间*/
        if(tGoods1.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE0) || tGoods1.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE1)
                || tGoods1.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE5)){
            List<TGoods> tGoodsList = tGoodsMapper.boxGoodsList(tGoods1.getGoodsBelongingType(),tGoods1.getGoodsBelongingId());
            this.toList(tGoodsList);
            tGoodsMapper.updateRollValueRangeBatch(tGoodsList);
        }
        return Response.success();
    }

    /**
     * 删除饰品信息信息
     *
     * @param goodsId 饰品信息ID
     * @return 结果
     */
    @Override
    public int deleteTGoodsById(String goodsId)
    {
        return tGoodsMapper.deleteTGoodsById(goodsId);
    }

    /**
     * 批量停用饰品信息
     * @param goodsIds
     * @return
     */
    @Override
    public Response batchStopTGoods(String[] goodsIds) {
        /**停用饰品无需关联其他限制条件均可停用*/
        tGoodsMapper.updateDelFlagTGoodsByIds(Constants.FAIL,goodsIds);
        return Response.success();
    }

    /**
     * 批量启用饰品信息
     * @param goodsIds
     * @return
     */
    @Override
    public Response batchEnableTGoods(String[] goodsIds) {
        /**根据条件获取出所有未启用饰品信息列表*/
        List<TGoods> tGoodsList = tGoodsMapper.bacthTGoodsList(Constants.FAIL,goodsIds);
        if (tGoodsList != null && tGoodsList.size() > 0){
           /**过滤出所属类型是为箱子的数据,并判断是否都为已启用状态*/
           List<String> boxIds = tGoodsList.stream().filter(bean -> bean.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE0))
                    .map(TGoods::getGoodsBelongingId).collect(Collectors.toList());
            if (boxIds != null && boxIds.size()>0) {
                List<TBox> tBoxList = tBoxMapper.getTBoxListBatch(Constants.FAIL,boxIds);
                if (tBoxList.size() > 0) {
                    return Response.fail(Constants.FAILCODE,"所选饰品中上一级中存在未启用的箱子，请先启用箱子!");
                }
            }
            /**过滤出所属类型是为ROLL房的数据,并判断是否都为已启用状态*/
            List<String> rollIds = tGoodsList.stream().filter(bean -> bean.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE1))
                    .map(TGoods::getGoodsBelongingId).collect(Collectors.toList());

            if (rollIds != null && rollIds.size()>0) {
               List<TRoll> tRollList = tRollMapper.getTRollListBatch(Constants.FAIL,rollIds);
                if (tRollList.size() > 0) {
                    return Response.fail(Constants.FAILCODE,"所选饰品中上一级中存在未启用的ROLL房，请先启用ROLL房!");
                }
            }
            /**批量启用饰品信息*/
            int rows = tGoodsMapper.updateDelFlagTGoodsByIds(Constants.SUCCESS,goodsIds);
            return rows > 0 ? Response.success() : Response.error();
        }else {
            return Response.fail(Constants.FAILCODE,"不存在未启用的!");
        }
    }
    /**
     * 获取幸运饰品下的饰品列表信息
     * @param tGoodsVo
     * @return
     */
    @Override
    public List<TGoods> luckyJewelryList(TGoodsVo tGoodsVo) {
        return tGoodsMapper.luckyJewelryList(tGoodsVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response<LuckyGoodsUpgrateResp> luckyGoodsUpgrateV2(TGoodsUpgrateVo req,String userId){
        LuckyGoodsUpgrateResp resp = new LuckyGoodsUpgrateResp();
        /**判断升级区间和概率是否一致*/
        if(!calculateProbability(req.getUpgateRate(),req.getLowerBound(),req.getUpperBound())){
            return Response.fail(Constants.FAILCODE,"升级的概率和选择区间范围值不一致");
        }

        /**获取用户基本信息*/
        TUser tUser = tUserMapper.selectTUserById(userId);
        if (StringUtils.isNull(tUser) || !Constants.SUCCESS.equals(tUser.getDelFlag())) {
            return Response.fail(Constants.FAILCODE,"用户不存在或已被冻结,请联系管理员！");
        }
        SysConfig sysConfig = sysConfigMapper.checkConfigKeyUnique("lucky_goods_upgrate_threshold");
        BigDecimal thresholdMoney = new BigDecimal(sysConfig.getConfigValue());

        if (tUser.getUserType().equals("0") && tUser.getUserTotalRecharge().compareTo(thresholdMoney) < 0){
            return Response.fail(Constants.FAILCODE,"累计充值满"+thresholdMoney.intValue()+"金币方可参加！");
        }

        List<String> goodsIds = req.getGoodsIds();
        List<TGoods> tGoodsList = tGoodsMapper.batchQueryByIds(goodsIds);
        if(goodsIds.size() != tGoodsList.size() ){
            return Response.fail("选择的幸运饰品中有不存在或者重复的");
        }
        if(new BigDecimal(req.getUpgateRate()).compareTo(new BigDecimal(0.85)) > 0
                || new BigDecimal(req.getUpgateRate()).compareTo(new BigDecimal(0.005)) < 0){
            return Response.fail("升级概率区间0.5%-85%");
        }

        SysConfig premium_rate_config = sysConfigMapper.checkConfigKeyUnique("luck_accessory_upgrade_premium_rate");
        BigDecimal premiumRate = premium_rate_config == null ? new BigDecimal("0.2") : new BigDecimal(premium_rate_config.getConfigValue());
        /**统计升级的饰品价值*/
        BigDecimal goodsPriceTotal = tGoodsList.stream()
                .map(tGoods -> tGoods.getGoodsPrice().multiply(BigDecimal.ONE.add(premiumRate)))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        /**升级实际需要花费的费用*/
        BigDecimal costFee = goodsPriceTotal.multiply(BigDecimal.valueOf(req.getUpgateRate())).setScale(2,BigDecimal.ROUND_HALF_UP);
        if(costFee.compareTo(BigDecimal.ONE) < 0){
            return Response.fail("低于1金币无法进行升级操作,请合理选择");
        }

        /**判断是否选择背包饰品抵扣*/
        List<TBackpack> backpackList = null;
        BigDecimal dkFee = BigDecimal.ZERO;
        if(StringUtils.isNotEmpty(req.getBbIds())){
            List<String> bbIds = req.getBbIds();
            String[] bs =bbIds.toArray(new String[0]);
            backpackList = tBackpackMapper.selectTBackpackBatchByIds(bs,userId);
            if (backpackList.size() !=  bbIds.size()) {
                return Response.fail(Constants.FAILCODE,"抵扣饰品状态已变更，请刷新页面重试");
            }
            /**判断背包抵扣的余额不可大于升级的饰品价值*/
            dkFee = backpackList.stream()
                    .map(bb -> bb.getGoodsPrice())
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            if(dkFee.compareTo(costFee) > 0){
                return Response.fail("升级时选择抵扣的背包物品价值不能高于实际支付费用！");
            }
        }

        /**判断用户的余额是否足够进行幸运饰品升级*/
        BigDecimal userBalanceBefore = tUser.getUserBalance();
        BigDecimal userSecondCurrencyBefore = tUser.getSecondCurrency();

        /**用户可消费金额*/
        BigDecimal consumableFee = userBalanceBefore.add(userSecondCurrencyBefore);

        if((consumableFee.add(dkFee)).compareTo(costFee) < 0){
            return Response.fail("余额不足，请前往充值");
        }
        List<TGoods> resultList = new ArrayList<>();
        try {
            /**获取默认保底饰品*/
            SysDictData ss = sysDictDataService.selectDictDataById(139L);
            String floorsGoodsId=ss.getListClass();
            /**获取价格区间的保底饰品*/
            List<TGoods> floorList = tGoodsMapper.floorsGoodsList(costFee.toString());
            if (floorList != null && floorList.size()>0) {
                floorsGoodsId = floorList.get(0).getGoodsId();
            }
            if (StringUtils.isEmpty(floorsGoodsId)) {
                return Response.fail(Constants.FAILCODE,"暂时补偿饰品缺货，请联系管理员！");
            }

            TGoods bcGoods = tGoodsMapper.selectTGoodsById(floorsGoodsId);
            if (bcGoods == null) {
                return Response.fail(Constants.FAILCODE,"请联系管理员,重新设置保底饰品！");
            }

            if(StringUtils.isNotEmpty(req.getBbIds())){
                /**批量更新背包状态*/
               int row =  tBackpackMapper.batchUpdateBBStatus(req.getBbIds(),Constants.BBSTATUS7);
               if(row != req.getBbIds().size()){
                   throw new CustomException("抵扣饰品状态已变更，升级无效，请刷新页面后重新选择饰品抵扣");
               }

               List<TBackpackDeduction> deductionList = backpackList.stream().map(bb -> TBackpackDeduction.builder()
                       .bbId(bb.getBbId())
                       .goodsId(bb.getGoodsId())
                       .createTime(DateUtils.getNowDate())
                       .goodsPrice(bb.getGoodsPrice())
                       .build()
               ).collect(Collectors.toList());
               tBackpackDeductionMapper.insertBatch(deductionList);
            }
            /**更新用户余额，并记录余额变更记录*/
            BigDecimal subFee = costFee.subtract(dkFee);
            /**开启后余额*/
            BigDecimal openAfterBalance = tUser.getUserBalance();
            /**开启后货币余额*/
            BigDecimal openAfterSecondCurrency = tUser.getSecondCurrency();
            if(openAfterBalance.compareTo(subFee) >=0){
                openAfterBalance = openAfterBalance.subtract(subFee);
            }else if(openAfterBalance.compareTo(BigDecimal.ZERO) > 0 && openAfterBalance.compareTo(subFee) < 0){
                openAfterSecondCurrency = openAfterSecondCurrency.subtract(subFee.subtract(openAfterBalance));
                openAfterBalance = BigDecimal.ZERO;
            }else {
                openAfterSecondCurrency = openAfterSecondCurrency.subtract(subFee);
            }
            tUser.setUserBalance(openAfterBalance);
            tUser.setSecondCurrency(openAfterSecondCurrency);
            int userrow = tUserMapper.updateTUserBalance(tUser);
            if(userrow == 0){
                throw new CustomException("用户信息版本变更，请重试");
            }

            String objectId = IdUtil.fastSimpleUUID();

            /**幸运饰品升级流程*/
            String userSeed = tUser.getUserSeed();
            String serverSeed = HashUtil.generateServerSeed();
            int nonce = HashUtil.generateNonce();
            String commonHash = HashUtil.commonHashCode(userSeed,serverSeed,nonce);
            Long rollValue = HashUtil.rollValue1(commonHash);

            Boolean upgrateFlag = checkRollSuccess(rollValue,req.getLowerBound(),req.getUpperBound());
            List<TGoodsUpgrate> tGoodsUpgrateList = new ArrayList<>();
            List<TBackpack> tBackpackList = new ArrayList<>();
            if(upgrateFlag){/**升级成功*/
                tBackpackList = tGoodsList.stream().map(tGoods -> {
                    String bbId = IdUtil.fastSimpleUUID();
                    tGoods.setBbId(bbId);
                    resultList.add(tGoods);

                    TBackpack backpack = new TBackpack();
                    backpack.setBbId(bbId);
                    backpack.setUserId(userId);
                    backpack.setGoodsId(tGoods.getGoodsId());
                    backpack.setGoodsBelongingType(Constants.GOOGSBLTYPE2);
                    backpack.setGoodsBelongingId(tGoods.getGoodsId());
                    backpack.setGoodsBelongingName(tGoods.getGoodsName());
                    backpack.setGoodsPrice(tGoods.getGoodsPrice());
                    backpack.setGoodsExprice(tGoods.getGoodsExprice());
                    backpack.setBbStatus(Constants.BBSTATUS0);
                    backpack.setDelFlag(Constants.SUCCESS);
                    backpack.setCreateTime(DateUtils.getNowDate());
                    backpack.setGoodsNum(1);
                    backpack.setGoodsType(tGoods.getGoodsType());
                    backpack.setUserPromotersId(tUser.getUserPromotersId());
                    BigDecimal openBoxPrice = tGoods.getPrice().multiply(BigDecimal.ONE.add(premiumRate)).multiply(BigDecimal.valueOf(req.getUpgateRate())).setScale(2,BigDecimal.ROUND_HALF_UP);
                    backpack.setOpenBoxPrice(openBoxPrice);
                    backpack.setAuditStatus(Constants.AUDITSTATUS0);
                    backpack.setBbGoodsName(tGoods.getGoodsName());
                    backpack.setBbGoodsPic(tGoods.getGoodsPic());
                    backpack.setBbGoodsGrate(tGoods.getGoodsGrate());
                    backpack.setUserSeed(userSeed);
                    backpack.setServerSeed(serverSeed);
                    backpack.setRollValue(rollValue);
                    backpack.setCommonHash(commonHash);
                    backpack.setNonce(nonce);
                    Map<String, Object> rangeMap = new HashMap<>();
                    rangeMap.put("lower",req.getLowerBound());
                    rangeMap.put("upper",req.getUpperBound());
                    backpack.setRollValueRange(JSON.toJSONString(rangeMap));
                    return backpack;
                }).collect(Collectors.toList());

                /**升级记录*/
                String objcetId = IdUtil.fastSimpleUUID();
                tGoodsUpgrateList = tGoodsList.stream().map(tGoods -> {
                    TGoodsUpgrate tGoodsUpgrate = new TGoodsUpgrate();
                    tGoodsUpgrate.setObjectId(objectId);
                    tGoodsUpgrate.setLuckyBbId(tGoods.getBbId());
                    tGoodsUpgrate.setLuckyGoodsId(tGoods.getGoodsId());
                    tGoodsUpgrate.setLuckyGoodsName(tGoods.getGoodsName());
                    tGoodsUpgrate.setLuckyGoodsPic(tGoods.getGoodsPic());
                    tGoodsUpgrate.setGoodsPrice(tGoods.getGoodsPrice());
                    tGoodsUpgrate.setGoodsExprice(tGoods.getGoodsPrice());
                    tGoodsUpgrate.setUserId(userId);
                    tGoodsUpgrate.setUserName(tUser.getUserName());
                    tGoodsUpgrate.setSuccessRate(BigDecimal.valueOf(req.getUpgateRate()));
                    BigDecimal openBoxPrice = tGoods.getGoodsPrice().multiply(BigDecimal.ONE.add(premiumRate)).multiply(BigDecimal.valueOf(req.getUpgateRate())).setScale(2,BigDecimal.ROUND_HALF_UP);
                    tGoodsUpgrate.setCost(openBoxPrice);
                    tGoodsUpgrate.setUpgradeStatus(upgrateFlag ? "0" : "1");
                    tGoodsUpgrate.setCreateTime(DateUtils.getNowDate());
                    tGoodsUpgrate.setPurchaseGoodsId(tGoods.getGoodsId());
                    /*上架价格*/
                    tGoodsUpgrate.setRemark3(BigDecimal.ZERO);
                    /*兑换价格*/
                    tGoodsUpgrate.setRemark4(BigDecimal.ZERO);
                    tGoodsUpgrate.setUpgradeFactor(null);
                    /**溢价值*/
                    tGoodsUpgrate.setPremiumRate(premiumRate);
                    return tGoodsUpgrate;
                }).collect(Collectors.toList());

            }else {
                String bbId = IdUtil.fastSimpleUUID();
                bcGoods.setBbId(bbId);
                resultList.add(bcGoods);

                TBackpack backpack = new TBackpack();

                backpack.setBbId(bbId);
                backpack.setUserId(userId);
                backpack.setGoodsId(bcGoods.getGoodsId());
                backpack.setGoodsBelongingType(Constants.GOOGSBLTYPE4);
                backpack.setGoodsBelongingId(bcGoods.getGoodsId());
                backpack.setGoodsBelongingName(bcGoods.getGoodsName());
                backpack.setGoodsPrice(bcGoods.getGoodsPrice());
                backpack.setGoodsExprice(bcGoods.getGoodsPrice());
                backpack.setBbStatus(Constants.BBSTATUS0);
                backpack.setDelFlag(Constants.SUCCESS);
                backpack.setCreateTime(DateUtils.getNowDate());
                backpack.setGoodsNum(1);
                backpack.setGoodsType(bcGoods.getGoodsType());
                backpack.setUserPromotersId(tUser.getUserPromotersId());
                backpack.setOpenBoxPrice(costFee);
                backpack.setAuditStatus(Constants.AUDITSTATUS0);
                backpack.setBbGoodsName(bcGoods.getGoodsName());
                backpack.setBbGoodsPic(bcGoods.getGoodsPic());
                backpack.setBbGoodsGrate(bcGoods.getGoodsGrate());
                backpack.setUserSeed(userSeed);
                backpack.setServerSeed(serverSeed);
                backpack.setRollValue(rollValue);
                backpack.setCommonHash(commonHash);
                backpack.setNonce(nonce);
                Map<String, Object> rangeMap = new HashMap<>();
                rangeMap.put("lower",req.getLowerBound());
                rangeMap.put("upper",req.getUpperBound());
                backpack.setRollValueRange(JSON.toJSONString(rangeMap));
                tBackpackList.add(backpack);

                String objcetId = IdUtil.fastSimpleUUID();
                TGoodsUpgrate tGoodsUpgrate = new TGoodsUpgrate();
                tGoodsUpgrate.setObjectId(objectId);
                tGoodsUpgrate.setGoodsPrice(bcGoods.getGoodsPrice());
                tGoodsUpgrate.setGoodsExprice(bcGoods.getGoodsPrice());
                tGoodsUpgrate.setGiveBbId(bbId);
                tGoodsUpgrate.setUserId(userId);
                tGoodsUpgrate.setUserName(tUser.getUserName());
                tGoodsUpgrate.setGiveGoodsId(bcGoods.getGoodsId());
                tGoodsUpgrate.setGiveGoodsName(bcGoods.getGoodsName());
                tGoodsUpgrate.setGiveGoodsPic(bcGoods.getGoodsPic());
                tGoodsUpgrate.setSuccessRate(BigDecimal.valueOf(req.getUpgateRate()));
                tGoodsUpgrate.setCost(costFee);
                tGoodsUpgrate.setUpgradeStatus(upgrateFlag ? "0" : "1");
                tGoodsUpgrate.setCreateTime(DateUtils.getNowDate());
                tGoodsUpgrate.setPurchaseGoodsId(bcGoods.getGoodsId());
                /*上架价格*/
                tGoodsUpgrate.setRemark3(bcGoods.getGoodsPrice());
                /*兑换价格*/
                tGoodsUpgrate.setRemark4(bcGoods.getGoodsPrice());
                tGoodsUpgrate.setUpgradeFactor(null);
                /**溢价值*/
                tGoodsUpgrate.setPremiumRate(null);
                tGoodsUpgrateList.add(tGoodsUpgrate);
            }
            /**批量添加幸运饰品*/
            tGoodsUpgrateMapper.batchInsert(tGoodsUpgrateList);
            /**批量添加背包*/
            tBackpackMapper.insertTBackpackBatch(tBackpackList);

            /**余额变更*/
            BigDecimal consumValue = costFee.multiply(BigDecimal.valueOf(0.25)).setScale(2,BigDecimal.ROUND_HALF_UP);
            TBalanceChange balanceChange= new TBalanceChange();
            balanceChange.setUserId(userId);
            balanceChange.setBalanceBefore(userBalanceBefore);
            balanceChange.setOperationType(Constants.OPERATIONTYPE2);
            balanceChange.setFrequency(req.getGoodsIds().size());
            balanceChange.setFee(costFee);
            balanceChange.setCorrespondingid(objectId);
            balanceChange.setCreateTime(DateUtils.getNowDate());
            balanceChange.setBalanceAfter(openAfterBalance);
            balanceChange.setSecondCurrencyBefore(userSecondCurrencyBefore);
            balanceChange.setSecondCurrencyAfter(openAfterSecondCurrency);
            balanceChange.setConsumeValue(consumValue);
            /**获利价值*/
            BigDecimal totalPrice = tBackpackList.stream().map(TBackpack::getGoodsPrice).reduce(BigDecimal.ZERO,BigDecimal::add);
            balanceChange.setProfitPrice(totalPrice);
            balanceChange.setCostFee(costFee);
            balanceChangeMapper.insertTBalanceChange(balanceChange);


            resp.setGoodsList(resultList);
            resp.setNonce(nonce);
            resp.setCommonHash(commonHash);
            resp.setRollValue(rollValue);
            resp.setServerSeed(serverSeed);
            resp.setUserSeed(userSeed);
            resp.setUpgrateFlag(upgrateFlag);

            /**计算战令和vip等级 经验*/
            if(consumValue.compareTo(BigDecimal.ZERO)>0){
                tVipUserService.vipStreamHandleV2(tUser.getUserId(),consumValue);
                tWarService.computeWarFlow(tUser.getUserId(),consumValue);
            }

            return Response.success(resp);
        } catch (CustomException e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Response.fail(e.getMessage());
        } catch (DuplicateKeyException e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Response.fail("抵扣饰品状态已变更，重新选择抵扣饰品");
        } catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error("幸运饰品升级异常:{}",e);
            return Response.fail("系统错误，请稍后重试");
        }

    }


    private boolean checkRollSuccess(Long rollValue, double successRangeStart, double successRangeEnd) {
        double normalizedRoll = rollValue / 10000.0; // 将点数值归一化到0到1之间

        // 调整检查逻辑以处理成功范围跨越 1.0 的情况
        if (successRangeStart > successRangeEnd) {
            return normalizedRoll >= successRangeStart || normalizedRoll <= successRangeEnd;
        } else {
            return normalizedRoll >= successRangeStart && normalizedRoll <= successRangeEnd;
        }
    }

    // 根据区间计算概率值
    private boolean calculateProbability( Double upgateRate, Double lowerBound,Double upperBound) {
        // 如果上界小于下界，说明跨越了 1，调整区间范围
        Double jsRate = null;
        if (upperBound < lowerBound) {
            jsRate = Arith.add(Arith.sub(1,lowerBound),upperBound);
        } else {
            jsRate = Arith.sub(upperBound,lowerBound);
        }
        return upgateRate.equals(jsRate);
    }



      /**
     * 后台饰品管理列表
     * @param tGoods
     * @return
     */
    @Override
    public List<TGoods> goodsListBack(TGoods tGoods) {
        return tGoodsMapper.goodsListBack(tGoods);
    }

    @Override
    public int updateTGoodsStockStatus(String goodsId, String goodsStockStatus) {
        return tGoodsMapper.updateTGoodsStockStatus(goodsId, goodsStockStatus);
    }

    @Override
    public List<TGoods> boxGoodsList(String goodsBelongingType, String goodsBelongingId) {
        return tGoodsMapper.boxGoodsList(goodsBelongingType, goodsBelongingId);
    }

    @Override
    public List<TGoods> boxTGoodsList(String goodsBelongingType, String goodsBelongingId) {
        return tGoodsMapper.boxGoodsList1(goodsBelongingType, goodsBelongingId);
    }

    /**
     * 批量添加饰品
     * @param list
     * @return
     */
    @Override
    @Transactional
    public Response batchAdd(TGoodsAddVo vo) {
        /**添加饰品*/
        List<TGoods> list = vo.getGoodsList();
        list.stream().forEach(item -> {
            TGoods tGoods = tGoodsPoolMapper.selectTGoodsById(item.getGoodsId());
            tGoods.setCreateTime(DateUtils.getNowDate());
            tGoods.setGoodsChance(new BigDecimal("0.01"));
            tGoods.setGoodsStockStatus("0");
            tGoods.setGoodsBelongingType(vo.getGoodsBelongingType());
            tGoods.setGoodsBelongingId(vo.getGoodsBelongingId());
            tGoods.setGoodsPutnum(1L);
            tGoods.setGoodsStocknum(1L);
            tGoods.setGoodsExprice(tGoods.getGoodsPrice());
            /**表示幸运饰品*/
            if (vo.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE2)) {
                tGoods.setMinSectionRate(new BigDecimal(0.05));
                tGoods.setMaxSectionRate(new BigDecimal(0.75));
                tGoods.setPremiumRate(new BigDecimal(0.05));
            }
            long num = 1;
            /**表示ROLL房饰品*/
            if (vo.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE1)) {
                if (StringUtils.isNotNull(item.getGoodsStocknum())){
                    num = item.getGoodsStocknum();
                }
            }
            for (int i=0;i<num;i++){
                tGoodsMapper.insertTGoods(tGoods);
            }
        });

        /**更新饰品的roll区间值*/
        if(vo.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE0) || vo.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE1)
        || vo.getGoodsBelongingType().equals(Constants.GOOGSBLTYPE5)){
            List<TGoods> tGoodsList = tGoodsMapper.boxGoodsList(vo.getGoodsBelongingType(),vo.getGoodsBelongingId());
            this.toList(tGoodsList);
            tGoodsMapper.updateRollValueRangeBatch(tGoodsList);
        }
        return Response.success();
    }

    @Override
    public Map<String, BigDecimal> luckyCount(String startTime,String endTime) {
        Map<String,BigDecimal> map = tBackpackMapper.luckyCountTotal(startTime, endTime);
        System.out.println(JSON.toJSONString(map));
        Map<String,BigDecimal> map1 = tBackpackMapper.luckyCountToday();
        System.out.println(JSON.toJSONString(map1));
        map.putAll(map1);
        return map;
    }

    @Override
    public List<LuckyTGoodsVo> luckyGoodsListBack(LuckyTGoodsVo tGoods) {
        List<LuckyTGoodsVo> list = tGoodsMapper.selectTGoodsListLuck(tGoods);
        if (list != null && list.size()>0){
            for (LuckyTGoodsVo luckyTGoodsVo : list) {
                Map<String,Object> map = tGoodsUpgrateMapper.luckCount(luckyTGoodsVo.getGoodsId());
                luckyTGoodsVo.setCostTotal(map.get("costTotal").toString());
                luckyTGoodsVo.setGoodsPriceTotal(map.get("goodsPriceTotal").toString());
                luckyTGoodsVo.setProfitTotal(map.get("profitTotal").toString());
                luckyTGoodsVo.setPartakeNum(map.get("partakeNum").toString());
            }
        }
        return list;
    }

    /**
     * 保底饰品列表
     * @param tGoods
     * @return
     */
    @Override
    public List<TGoods> floorsGoodsListBack(TGoods tGoods) {
        return tGoodsMapper.selectTGoodsListSz(tGoods);
    }

    @Override
    public Response floorsTGoodsAdd(TGoods tGoods) {
        if (!(StringUtils.isNotEmpty(tGoods.getGoodsId()) && StringUtils.isNotNull(tGoods.getMinPrice()) && StringUtils.isNotNull(tGoods.getMaxPrice()))) {
            return Response.fail(Constants.FAILCODE,"饰品ID、价格区间必填！");
        }
        if (tGoods.getMaxPrice().compareTo(tGoods.getMinPrice()) < 0) {
            return Response.fail(Constants.FAILCODE,"价格区间错误！");
        }
        /**判断价格区间是否重复*/
        int row = tGoodsMapper.floorsSection(tGoods.getMinPrice().toString(),tGoods.getMaxPrice().toString());
        if (row>0) {
            return Response.fail(Constants.FAILCODE,"价格区间重复！");
        }

        TGoods bean = tGoodsPoolMapper.selectTGoodsById(tGoods.getGoodsId());
        bean.setCreateTime(DateUtils.getNowDate());
        bean.setGoodsChance(new BigDecimal("0.01"));
        bean.setGoodsStockStatus("0");
        bean.setGoodsPutnum(1L);
        bean.setGoodsStocknum(1L);
        bean.setGoodsBelongingType(Constants.GOOGSBLTYPE4);
        bean.setMinPrice(tGoods.getMinPrice());
        bean.setMaxPrice(tGoods.getMaxPrice());
        bean.setGoodsExprice(bean.getGoodsPrice());
        int ss = tGoodsMapper.insertTGoods(bean);
        return Response.success();
    }

    @Override
    public Response floorsTGoodsEdit(TGoods tGoods) {
        if (!(StringUtils.isNotEmpty(tGoods.getGoodsId()) && StringUtils.isNotNull(tGoods.getMinPrice()) && StringUtils.isNotNull(tGoods.getMaxPrice()))) {
            return Response.fail(Constants.FAILCODE,"饰品ID、价格区间必填！");
        }
        /**判断价格区间是否重复*/
        int row = tGoodsMapper.floorsSectionBygoodsId(tGoods.getMinPrice().toString(),tGoods.getMaxPrice().toString(),tGoods.getGoodsId());
        if (row>0) {
            return Response.fail(Constants.FAILCODE,"价格区间重复！");
        }
        TGoods tGoods1 = new TGoods();
        tGoods1.setGoodsId(tGoods.getGoodsId());
        tGoods1.setMinPrice(tGoods.getMinPrice());
        tGoods1.setMaxPrice(tGoods.getMaxPrice());
        tGoods1.setUpdateTime(DateUtils.getNowDate());
        tGoodsMapper.updateTGoods(tGoods1);
        return Response.success();
    }

    @Override
    public int premiumSet(String type, String val) {
        return tGoodsMapper.goodsPremiumSet(type, val);
    }

    @Override
    public String defaultTGoodsSet(String goodsId) {
        TGoods bean = tGoodsPoolMapper.selectTGoodsById(goodsId);
        bean.setCreateTime(DateUtils.getNowDate());
        bean.setGoodsChance(new BigDecimal("0.01"));
        bean.setGoodsStockStatus("0");
        bean.setGoodsPutnum(1L);
        bean.setGoodsStocknum(1L);
        bean.setGoodsBelongingType(Constants.GOOGSBLTYPE4);
        bean.setMinPrice(new BigDecimal(0));
        bean.setMaxPrice(new BigDecimal(0));
        int ss = tGoodsMapper.insertTGoods(bean);
        return bean.getGoodsId();
    }

    @Override
    public Response floorsTGoodsEditBattle(TGoods tGoods) {
        if (!(StringUtils.isNotEmpty(tGoods.getGoodsId()) && StringUtils.isNotNull(tGoods.getMinPrice()) && StringUtils.isNotNull(tGoods.getMaxPrice()))) {
            return Response.fail(Constants.FAILCODE,"饰品ID、价格区间必填！");
        }
        /**判断价格区间是否重复*/
        int row = tGoodsMapper.floorsSectionBygoodsIdBattle(tGoods.getMinPrice().toString(),tGoods.getMaxPrice().toString(),tGoods.getGoodsId());
        if (row>0) {
            return Response.fail(Constants.FAILCODE,"价格区间重复！");
        }
        TGoods tGoods1 = new TGoods();
        tGoods1.setGoodsId(tGoods.getGoodsId());
        tGoods1.setMinPrice(tGoods.getMinPrice());
        tGoods1.setMaxPrice(tGoods.getMaxPrice());
        tGoods1.setUpdateTime(DateUtils.getNowDate());
        tGoodsMapper.updateTGoods(tGoods1);
        return Response.success();
    }

    @Override
    public Response floorsTGoodsBattleAdd(TGoods tGoods) {
        if (!(StringUtils.isNotEmpty(tGoods.getGoodsId()) && StringUtils.isNotNull(tGoods.getMinPrice()) && StringUtils.isNotNull(tGoods.getMaxPrice()))) {
            return Response.fail(Constants.FAILCODE,"饰品ID、价格区间必填！");
        }
        if (tGoods.getMaxPrice().compareTo(tGoods.getMinPrice()) < 0) {
            return Response.fail(Constants.FAILCODE,"价格区间错误！");
        }
        /**判断价格区间是否重复*/
        int row = tGoodsMapper.floorsSectionBattle(tGoods.getMinPrice().toString(),tGoods.getMaxPrice().toString());
        if (row>0) {
            return Response.fail(Constants.FAILCODE,"价格区间重复！");
        }

        TGoods bean = tGoodsPoolMapper.selectTGoodsById(tGoods.getGoodsId());
        bean.setCreateTime(DateUtils.getNowDate());
        bean.setGoodsChance(new BigDecimal("0.01"));
        bean.setGoodsStockStatus("0");
        bean.setGoodsPutnum(1L);
        bean.setGoodsStocknum(1L);
        bean.setGoodsBelongingType(Constants.GOOGSBLTYPE6);
        bean.setMinPrice(tGoods.getMinPrice());
        bean.setMaxPrice(tGoods.getMaxPrice());
        bean.setGoodsExprice(bean.getGoodsPrice());
        int ss = tGoodsMapper.insertTGoods(bean);
        return Response.success();
    }

    @Override
    public String defaultTGoodsSetBattle(String goodsId) {
        TGoods bean = tGoodsPoolMapper.selectTGoodsById(goodsId);
        bean.setCreateTime(DateUtils.getNowDate());
        bean.setGoodsChance(new BigDecimal("0.01"));
        bean.setGoodsStockStatus("0");
        bean.setGoodsPutnum(1L);
        bean.setGoodsStocknum(1L);
        bean.setGoodsBelongingType(Constants.GOOGSBLTYPE6);
        bean.setMinPrice(new BigDecimal(0));
        bean.setMaxPrice(new BigDecimal(0));
        int ss = tGoodsMapper.insertTGoods(bean);
        return bean.getGoodsId();
    }

    @Override
    public List<TGoods> shoppingMallList(TGoodsVo tGoods) {
        return tGoodsMapper.shoppingMallList(tGoods);
    }

    /**
     * 饰品商城  购买
     * @param userId 用户id
     * @param goodsIds 饰品id  多个用逗号拼接
     * @param goodsNum 购买饰品数量
     * @return  AjaxResult
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response shoppingBuy(ShoppingVo shoppingVo) throws Exception {
        String userId = shoppingVo.getUserId();
        List<String>  goodsIds = shoppingVo.getGoodsIds();

        String ip = IpUtils.getIpAddr(ServletUtils.getRequest());

        /**获取用户基本信息*/
        TUser tUser = tUserMapper.selectTUserById(userId);
        if (StringUtils.isNull(tUser) || Constants.FAIL.equals(tUser.getDelFlag())) {
            return Response.fail(Constants.FAILCODE,"用户不存在或已被冻结账号！");
        }
        if (goodsIds == null || goodsIds.size() == 0){
            return Response.fail(Constants.FAILCODE,"请选择购买的饰品！");
        }
        List<TGoods> allGoods = tGoodsMapper.bacthTGoodsList("0",goodsIds.toArray(new String[0]));
        if(CollectionUtil.isEmpty(allGoods)){
            return Response.fail(Constants.FAILCODE,"饰品不存在！");
        }
        /**判断购买金额是否等于购买饰品实际金额*/
        BigDecimal goodsprice = BigDecimal.ZERO;
        /**分组汇总*/
        Map<String, Long> map = goodsIds.stream().collect(Collectors.groupingBy(String::toString,Collectors.counting()));
        /**校验商城的商品*/
        for (Map.Entry<String, Long> entry : map.entrySet()) {
            String goodsId = entry.getKey();
            Long num = entry.getValue();

            Optional<TGoods> optional = allGoods.stream().filter(goods -> goods.getGoodsId().equals(goodsId)).findFirst();
            if(!optional.isPresent()){
                return Response.fail(Constants.FAILCODE,"饰品不存在！");
            }
            TGoods tGood = optional.get();
            if (!Constants.GOOGSBLTYPE3.equals(tGood.getGoodsBelongingType())){
                return Response.fail(Constants.FAILCODE,"选择的饰品不存在！请刷新重试！");
            }
            if (Long.parseLong(entry.getValue().toString()) > tGood.getGoodsStocknum()){
                return Response.fail(Constants.FAILCODE,tGood.getGoodsName() +": 库存数量不足！");
            }
            goodsprice = goodsprice.add(tGood.getGoodsPrice().multiply(new BigDecimal(num)));
        }

        /**判断用户第二货币是否充足*/
        BigDecimal secondCurrency = tUser.getSecondCurrency();
        if(secondCurrency.compareTo(goodsprice) < 0){
            return Response.fail(Constants.FAILCODE,"第二套货币余额不足");
        }


        List<ShoppingGoods> list = new ArrayList<>();
        for (Map.Entry<String, Long> entry : map.entrySet()) {
            String goodsId = entry.getKey();
            Long num = entry.getValue();
            TGoods tGood = allGoods.stream().filter(goods -> goods.getGoodsId().equals(goodsId)).findFirst().get();

            ShoppingGoods shoppingGoods = new ShoppingGoods();
            BeanUtils.copyProperties(tGood,shoppingGoods);
            shoppingGoods.setGoodsNum(num);
            list.add(shoppingGoods);
            tGood.setGoodsStocknum(tGood.getGoodsStocknum()-num);
            int row = tGoodsMapper.updateTGoodsStockNumAppoint(tGood);
            if (row == 0){
                log.error("更新饰品商城中库存失败："+shoppingVo.toString());
                throw new CustomException("网络延迟,请重试! ");
            }
        }

        List<TBackpack> backpackList = new ArrayList<>();
        if (secondCurrency.compareTo(goodsprice) >= 0){
            for (ShoppingGoods bean1:list) {
                for (int i=0;i<bean1.getGoodsNum();i++){
                    TGoods bean = new TGoods();
                    BeanUtils.copyProperties(bean1,bean);
                    /**插入背包表*/
                    String bbId = DateUtils.dateTimeNow()+ IdUtils.fastUUID().substring(0,8);
                    TBackpack backpack = new TBackpack();
                    backpack.setBbId(bbId);
                    backpack.setUserId(userId);
                    backpack.setGoodsId(bean.getGoodsId());
                    backpack.setGoodsBelongingType(Constants.GOOGSBLTYPE3);
                    backpack.setGoodsBelongingId(bean.getGoodsBelongingId());
                    backpack.setGoodsBelongingName(bean.getGoodsName());
                    backpack.setGoodsPrice(bean.getGoodsPrice());
                    backpack.setBbStatus(Constants.BBSTATUS0);
                    backpack.setDelFlag(Constants.SUCCESS);
                    backpack.setCreateTime(DateUtils.getNowDate());
                    backpack.setGoodsExprice(bean.getGoodsExprice());
                    backpack.setGoodsType(bean.getGoodsType());
                    backpack.setGoodsNum(1);
                    backpack.setUserPromotersId(tUser.getUserPromotersId());
                    backpack.setOpenBoxPrice(bean.getGoodsPrice());
                    backpack.setAuditStatus(Constants.AUDITSTATUS0);
                    backpack.setIp(ip);
                    backpack.setBbGoodsName(bean.getGoodsName());
                    backpack.setBbGoodsPic(bean.getGoodsPic());
                    backpack.setBbGoodsGrate(bean.getGoodsGrate());
                    /**余额算法*/
                    backpackList.add(backpack);
                    secondCurrency = secondCurrency.subtract(bean.getGoodsPrice());
                }
            }
            /**批量插入背包信息表*/
            int row = tBackpackMapper.insertTBackpackBatch(backpackList);
            if (row == 0){
                log.error("插入背包表失败！");
                throw new CustomException("网络延迟，请重试！");
            }

            /*插入余额变更表*/
            TBalanceChange balanceChange = new TBalanceChange();
            balanceChange.setUserId(userId);
            balanceChange.setBalanceBefore(tUser.getUserBalance());
            balanceChange.setOperationType(Constants.OPERATIONTYPE3);
            balanceChange.setFrequency(goodsIds.size());
            balanceChange.setBalanceAfter(tUser.getUserBalance());
            balanceChange.setCorrespondingid(StringUtils.join(goodsIds.toArray(),","));
            balanceChange.setCreateTime(DateUtils.getNowDate());
            balanceChange.setFee(goodsprice);
            balanceChange.setSecondCurrencyBefore(tUser.getSecondCurrency());
            balanceChange.setSecondCurrencyAfter(secondCurrency);
            balanceChange.setConsumeValue(BigDecimal.ZERO);
            balanceChange.setProfitPrice(goodsprice);
            balanceChange.setCostFee(goodsprice);
            balanceChangeMapper.insertTBalanceChange(balanceChange);

            /**修改用户的余额*/
            tUser.setSecondCurrency(secondCurrency);
            tUser.setUpdateTime(DateUtils.getNowDate());
            int row1 = tUserMapper.updateTUserBalance(tUser);
            if (row1 == 0 ){
                throw new CustomException("网络延迟,请重试! ");
            }
        }else {
            return Response.fail(Constants.FAILCODE,"余额不足，请充值后再购买！");
        }
        return Response.success("购买成功，请在背包中查看！");
    }

    /**
     * 饰品商城统计
     * @return
     */
    @Override
    public Map<String, Object> shoppingMallCount() {
        Map<String, Object> total = tBackpackMapper.shoppingMallTotal();
        Map<String, Object> today = tBackpackMapper.shoppingMallToday();
        total.putAll(today);
        return total;
    }

    /**
     * 饰品商城 后台饰品统计列表
     * @param tGoodsShoppingBackVo
     * @return
     */
    @Override
    public List<TGoodsShoppingBackVo> shoppingMallListBack(TGoodsShoppingBackVo tGoodsShoppingBackVo) {
        return tGoodsMapper.shoppingMallListBack(tGoodsShoppingBackVo);
    }

    /**
     * 饰品商城  饰品添加
     * @param tGoodsShoppingBackVo
     * @return
     */
    @Override
    public Response shoppingMallAdd(TGoodsShoppingBackVo tGoodsShoppingBackVo) {
        TGoods tGoods = tGoodsPoolMapper.selectTGoodsById(tGoodsShoppingBackVo.getGoodsPoolId());
        tGoods.setCreateTime(DateUtils.getNowDate());
        tGoods.setGoodsChance(new BigDecimal("0.01"));
        tGoods.setGoodsStockStatus("0");
        tGoods.setGoodsBelongingType(Constants.GOOGSBLTYPE3);
        tGoods.setGoodsBelongingId(null);
        tGoods.setGoodsPutnum(tGoodsShoppingBackVo.getAddStocknum() == null ? 99999L : tGoodsShoppingBackVo.getAddStocknum());
        tGoods.setGoodsStocknum(tGoodsShoppingBackVo.getAddStocknum() == null ? 99999L : tGoodsShoppingBackVo.getAddStocknum());
        tGoods.setGoodsExprice(tGoods.getGoodsPrice());
        tGoods.setGoodsGrate(tGoodsShoppingBackVo.getGoodsGrate() == null ? tGoods.getGoodsGrate() : tGoodsShoppingBackVo.getGoodsGrate());
        int i = tGoodsMapper.insertTGoods(tGoods);
        return i > 0 ? Response.success() : Response.error();
    }

    @Override
    public Response shoppingMallUpdate(TGoodsShoppingBackVo tGoodsShoppingBackVo) {
        TGoods tGoods = tGoodsMapper.selectTGoodsById(tGoodsShoppingBackVo.getGoodsId());
        if (tGoods == null){
            return Response.fail(Constants.FAILCODE,"不存在该饰品!");
        }
        if (tGoods.getGoodsStocknum()+tGoodsShoppingBackVo.getAddStocknum() < 0){
            return Response.fail(Constants.FAILCODE,"库存数量不能为负数,最小为0!");
        }
        tGoods.setGoodsStocknum(tGoods.getGoodsStocknum()+tGoodsShoppingBackVo.getAddStocknum());
        if (StringUtils.isNotEmpty(tGoodsShoppingBackVo.getGoodsGrate())){
            tGoods.setGoodsGrate(tGoodsShoppingBackVo.getGoodsGrate());
        }
        tGoods.setDelFlag(tGoodsShoppingBackVo.getDelFlag());
        tGoods.setUpdateTime(DateUtils.getNowDate());
        if (StringUtils.isNotNull(tGoodsShoppingBackVo.getGoodsPrice())){
            tGoods.setGoodsPrice(tGoodsShoppingBackVo.getGoodsPrice());
            tGoods.setGoodsExprice(tGoodsShoppingBackVo.getGoodsPrice());
        }
        int i = tGoodsMapper.updateTGoods(tGoods);
        return i > 0 ? Response.success() : Response.error();
    }

    @Override
    public List<TBackPackShoppingBackVo> shoppingMallBuyList(TBackPackShoppingBackVo tBackPackShoppingBackVo) {
        return tBackpackMapper.shoppingMallBuyList(tBackPackShoppingBackVo);
    }

    @Override
    public int  editDelfalg(String goodsId, String delFlag) {
        return tGoodsMapper.updateDelFlagTGoodsByIds(delFlag,goodsId.split(","));
    }

    @Override
    public Response updateGoodsPoolPrice(String type,List<String> boxIds){
        List<TGoods> list = tGoodsMapper.getMarketHashNameAll(type,boxIds);
        List<List<TGoods>> listGroup = new ArrayList<>();

        /**饰品商城溢价*/
        SysConfig mallPremiumRatio = sysConfigMapper.checkConfigKeyUnique("mall_premium_ratio");
        String premiumRatio = mallPremiumRatio.getConfigValue() == null ? "0" : mallPremiumRatio.getConfigValue();

        /**饰品商城更新价格总库存自动下架库存数量设置*/
        SysConfig goodsMallStocknumRank = sysConfigMapper.checkConfigKeyUnique("goods_mall_stocknum_rank");
        String stocknum = mallPremiumRatio.getConfigValue() == null ? "0" : goodsMallStocknumRank.getConfigValue();

        if(type.equals(Constants.GOOGSBLTYPE0)){
            List<String> faileList = new ArrayList<>();
            if (!StringUtils.isEmpty(boxIds)){
                for (String boxId:boxIds){
                    List<TGoods> newList = new ArrayList<>();
                    list.forEach((bean)-> {
                        String belongingId = bean.getGoodsBelongingId();
                        if(bean.getGoodsBelongingId().equals(boxId)){
                            newList.add(bean);
                        }
                    });
                    if(!CollectionUtils.isEmpty(newList)){
                        boolean flag = commonService.batchUpdateBoxGoodsPoolPrice(type, newList,boxId,premiumRatio,stocknum);
                        if(!flag){
                            faileList.add(boxId);
                        }
                    }
                }
                if(faileList.size() == 0){
                    return  Response.success("更新箱子价格成功");
                }else {
                    return  Response.fail("更新箱子价格失败箱子ID:"+JSON.toJSONString(faileList));
                }
            }else {
                return  Response.fail("请选择更新箱子");
            }
        }else {
            int listSize = list.size();
            int pageSize = 100;
            for (int i = 0; i < listSize; i += pageSize) {
                if (i + pageSize > listSize) {
                    pageSize = listSize - i;
                }
                List<TGoods> newList = list.subList(i, i + pageSize);
                listGroup.add(newList);
            }
            if (listGroup.size() > 0) {
                for (List<TGoods> tGoodsList : listGroup) {
                    try {
                        this.batchUpdateGoodsPoolPrice(type, tGoodsList,null,premiumRatio,stocknum);
                    } catch (Exception e) {
                        log.error("部分更新失败：失败条数");
                    }
                }
            }
        }
        return Response.success("更新价格成功");
    }

    @Override
    /**
     * 修改幸运饰品溢价值
     */
    public int updatePremiumRate(String premiumRate, String goodsbelongingtype) {
        return tGoodsMapper.updatePremiumRate(premiumRate, goodsbelongingtype);
    }

    /**
     * 默认排雷保底饰品添加
     * @param goodsId
     * @return
     */
    @Override
    public TGoods defaultTGoodsSetMineClear(String goodsId) {
        TGoods bean = tGoodsPoolMapper.selectTGoodsById(goodsId);
        bean.setCreateTime(DateUtils.getNowDate());
        bean.setGoodsChance(new BigDecimal("0.01"));
        bean.setGoodsStockStatus("0");
        bean.setGoodsPutnum(1L);
        bean.setGoodsStocknum(1L);
        bean.setGoodsBelongingType(Constants.GOOGSBLTYPE10);
        bean.setWhetherFloors(0);
        tGoodsMapper.insertTGoods(bean);
        return bean;
    }

//    /**
//     *  更新饰品价格
//     * @param type
//     * @param marketHashNameList
//     * @param boxId
//     * @param premiumRatio
//     * @param stocknum
//     */
//    public void batchUpdateGoodsPoolPrice(String type, List<TGoods> marketHashNameList,String boxId,String premiumRatio,String stocknum ) throws Exception{
//        Map map = new HashMap();
//        map.put("appId", Constants.APPID);
//        List<String> marketHashLists = marketHashNameList.stream().map(TGoods::getMarketHashName).collect(Collectors.toList());
//        map.put("marketHashNameList", marketHashLists);
//        String result = null;
//        try {
//            result = HttpsUtils.sendPost("https://app.zbt.com/open/product/price/info?app-key="+Constants.APP_KEY+"&language=zh_CN", JSON.toJSONString(map), null);
//        } catch (Exception e) {
//            log.error(e.getMessage());
//        }
//        log.info(result);
//        if (result != null) {
//            JSONObject jsonObject = JSON.parseObject(result);
//            List<ZBTGoodsVo> zbtGoodsVos = JSONArray.parseArray(jsonObject.getString("data"), ZBTGoodsVo.class);
//            List<ZBTGoodsVo> zbtGoodsVos1 = new ArrayList<>();
//            if(zbtGoodsVos != null && zbtGoodsVos.size() > 0){
//                /**更新查询到的饰品的信息*/
//                for (ZBTGoodsVo zbtGoodsPoolVo : zbtGoodsVos) {
//                    if (zbtGoodsPoolVo.getPrice() != null){
//                        if (Constants.GOOGSBLTYPE3.equals(type)) {
//                            zbtGoodsPoolVo.setAutoDeliverPricePremium(zbtGoodsPoolVo.getPrice().add(zbtGoodsPoolVo.getPrice().multiply(new BigDecimal(premiumRatio))).setScale(2, BigDecimal.ROUND_HALF_UP));
//                        }else {
//                            zbtGoodsPoolVo.setAutoDeliverPricePremium(zbtGoodsPoolVo.getPrice());
//                        }
//                        zbtGoodsVos1.add(zbtGoodsPoolVo);
//                    }
//                }
//                if (zbtGoodsVos1.size() > 0) {
//                    tGoodsMapper.updateTGoodPrice(type, zbtGoodsVos1,boxId,Integer.parseInt(stocknum));
//                }
//
//                /**更新ZBT查询不到的饰品信息,默认设置饰品为库存不足，并且幸运饰品和商城饰品自动下架*/
//                List<TGoods> notExitList = new ArrayList<>();
//                for (TGoods tGoods : marketHashNameList) {
//                    if (StringUtils.isNotEmpty(tGoods.getZBT())){
//                        long num = zbtGoodsVos1.stream().filter(bean-> bean.getItemId().equals(tGoods.getZBT())).count();
//                        if (num == 0){
//                            notExitList.add(tGoods);
//                        }
//                    }
//                }
//                if(notExitList.size()>0){
//                    tGoodsMapper.updateTGoodNotExist(notExitList);
//                }
//            }
//
//        }
//    }

    /**
     *  更新悠悠有品饰品价格
     * @param type
     * @param marketHashNameList
     * @param boxId
     * @param premiumRatio
     * @param stocknum
     */
    public void batchUpdateGoodsPoolPrice(String type, List<TGoods> marketHashNameList,String boxId,String premiumRatio,String stocknum ) throws Exception{
        List<Integer> templateIds = marketHashNameList.stream().map(TGoods::getZBT).distinct().collect(Collectors.toList());
        List<SaleResponse> saleResponseList = commonService.priceInfoYY(templateIds);
        if(CollectionUtil.isNotEmpty(saleResponseList)){
            if (Constants.GOOGSBLTYPE3.equals(type)) {
                saleResponseList.forEach(bean -> {
                    SaleCommodityResponse saleCommodityResponse = bean.getSaleCommodityResponse();
                    if(saleCommodityResponse != null && StringUtils.isNotEmpty(saleCommodityResponse.getMinSellPrice())){
                        BigDecimal goodsPrice = new BigDecimal(saleCommodityResponse.getMinSellPrice()).multiply(BigDecimal.ONE.add(new BigDecimal(premiumRatio))).setScale(2,BigDecimal.ROUND_HALF_UP);
                        saleCommodityResponse.setMinSellPrice(goodsPrice.toString());
                        bean.setSaleCommodityResponse(saleCommodityResponse);
                    }
                });
            }
            /**更新查询到的饰品的信息*/
            tGoodsMapper.updateTGoodPriceYY(type, saleResponseList,boxId,Integer.parseInt(stocknum));

            /**更新ZBT查询不到的饰品信息,默认设置饰品为库存不足，并且幸运饰品和商城饰品自动下架*/
            List<TGoods> notExitList = new ArrayList<>();
            for (TGoods tGoods : marketHashNameList) {
                if (tGoods.getZBT() != null){
                    long num = saleResponseList.stream().filter(bean-> tGoods.getZBT().equals(bean.getSaleTemplateResponse().getTemplateId())).count();
                    if (num == 0){
                        notExitList.add(tGoods);
                    }
                }
            }
            if(notExitList.size()>0){
                tGoodsMapper.updateTGoodNotExist(notExitList);
            }
        }
    }


    /**
     * 更新箱子的价格以及更新箱子下面饰品的品级
     * @param boxIds
     */
    @Override
    public void batchUpdateBoxPrice(List<String> boxIds) {
        /*查询出箱子中所有饰品*/
        List<TGoods> goodsList = tGoodsMapper.selectboxGoodsList(boxIds);
        /*查询出所有箱子*/
        List<TBox> boxList = tBoxMapper.getTBoxListBatch(null, boxIds);

        List<TGoods> grateGoodsList = new ArrayList<>();
        List<TBox> updateBoxList = new ArrayList<>();
        if (boxList.size() > 0) {
            for (TBox box : boxList) {
                /**推广积分箱子的箱子积分不更新*/
                if (!box.getBoxType().equals(Constants.BOXTYPE3)){
                    List<TGoods> goods = goodsList.stream().filter(bean -> bean.getGoodsBelongingId().equals(box.getBoxId())).collect(Collectors.toList());
                    /**计算出所有饰品价格,算出箱子价格*/
                    BigDecimal sumPrice = goods.stream().map(be-> be.getGoodsPrice().multiply(be.getGoodsChance())).reduce(BigDecimal.ZERO, BigDecimal::add);
                    BigDecimal excessValue = box.getExcessValue() == null ? new BigDecimal(0.05) : box.getExcessValue();
                    BigDecimal boxPrice = sumPrice.multiply((new BigDecimal(1).add(excessValue))).setScale(2, BigDecimal.ROUND_HALF_UP);
                    log.info("箱子价格更新：箱子ID:{},原价格:{},推荐价格:{},溢价值:{},溢价价格:{}",box.getBoxId(),box.getBoxPrice(),sumPrice,excessValue,boxPrice);
                    box.setBoxPrice(boxPrice);
                    /**添加到箱子价格更新集合中*/
                    updateBoxList.add(box);

                    if(box.getIsUpdateGoodsGrate()){
                        /**根据箱子价格来设置饰品品级*/
                        this.updateTGoodsGrate(box,goods);
                        /**添加到统一品级更新饰品品级集合中*/
                        grateGoodsList.addAll(goods);
                    }
                }
            }
            if (updateBoxList.size() > 0){
                /**批量更新箱子价格*/
                tBoxMapper.updateBoxPriceBatch(updateBoxList);
            }
            if (grateGoodsList.size() > 0){
                /**批量更新饰品品级*/
                tGoodsMapper.updateGrateBatch(grateGoodsList);
            }
        }
    }



    /**
     * 根据箱子价格来设置饰品品级
     * @param tbox
     * @param list
     */
    public  void updateTGoodsGrate(TBox tbox,List<TGoods> list){
        /**
         * 若金设为x ， 红设为 y ，紫设为z ，点击【更新箱子价格】时。箱子最新价格为p ，
         * 则满足饰品价格≥x*p的饰品背景颜色为金；
         * 满足y*p≤饰品价格＜x*p的饰品背景颜色为红；
         * 满足z*p≤饰品价格＜y*p的饰品背景颜色为紫，其余箱子内饰品颜色为蓝。
         * 若有一个输入框为0，代表饰品跳过此颜色。
         * 即若y=0, 则满足饰品价格≥x*p的饰品背景颜色为金；
         * 满足z*p≤饰品价格＜x*p的饰品背景颜色为紫，其余饰品颜色为蓝
         */

        for (TGoods tGoods : list) {
            /**满足条件设置金品级饰品*/
            if(tbox.getGoldGradePrice() != null && tbox.getGoldGradePrice().compareTo(new BigDecimal(0)) > 0){
                BigDecimal gratePrice = tbox.getBoxPrice().multiply(tbox.getGoldGradePrice());
                if (tGoods.getGoodsPrice().compareTo(gratePrice) >= 0){
                    tGoods.setGoodsGrate("0");
                    continue;
                }
            }
            /**满足条件设置红品级饰品*/
            if(tbox.getRedGradePrice() != null && tbox.getRedGradePrice().compareTo(new BigDecimal(0)) > 0){
                BigDecimal gratePrice =  tbox.getBoxPrice().multiply(tbox.getRedGradePrice());
                if (tGoods.getGoodsPrice().compareTo(gratePrice) >= 0){
                    tGoods.setGoodsGrate("1");
                    continue;
                }
            }

            /**满足条件设置紫品级饰品*/
            if(tbox.getPurpleGratePrice() != null && tbox.getPurpleGratePrice().compareTo(new BigDecimal(0)) > 0){
                BigDecimal gratePrice =  tbox.getBoxPrice().multiply(tbox.getPurpleGratePrice());
                if (tGoods.getGoodsPrice().compareTo(gratePrice) >= 0){
                    tGoods.setGoodsGrate("2");
                    continue;
                }
            }

            /**如果其他条件都不满足，则设置为蓝*/
            tGoods.setGoodsGrate("3");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBoxInfo() {
        /**全量更新箱子价格*/
        tGoodsMapper.updateBoxGoodsPrice();
        /**全量更新箱子内的饰品品级以及箱子价格*/
        List<String> boxIds = tBoxMapper.getAllBoxId();
        batchUpdateBoxPrice(boxIds);
    }
}
